﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.Diagnostics;

namespace Catalyst.Web.DynamicData.Design
{
    internal abstract class FilterTemplateCreator
    {
        protected const string FilterTemplatesFolderName = "FilterTemplates";
        protected const string DynamicDataFolderName = "DynamicData";

        protected Project Project { get; private set; }

        private static Dictionary<string, Func<Project, FilterTemplateCreator>> _filterTemplateCreators = InitializeCreators();

        private static Dictionary<string, Func<Project, FilterTemplateCreator>> InitializeCreators()
        {
            var creators = new Dictionary<string, Func<Project, FilterTemplateCreator>>();
            creators.Add(CodeModelLanguageConstants.vsCMLanguageCSharp, p => new CSharpFilterTemplateCreator(p));
            creators.Add(CodeModelLanguageConstants.vsCMLanguageVB, p => new VisualBasicFilterTemplateCreator(p));
            return creators;
        }
        
        public static FilterTemplateCreator GetTemplateCreator(Project project)
        {
            if(project == null)
                throw new ArgumentNullException("project");

            return _filterTemplateCreators[project.CodeModel.Language](project);
        }

        protected FilterTemplateCreator(Project project)
        {
            if (project == null)
                throw new ArgumentNullException("project");
            
            Project = project;
        }

        private ProjectItem _dynamicDataFolder;

        protected ProjectItem DynamicDataFolder
        {
            get
            {
                if (_dynamicDataFolder == null)
                {
                    try
                    {
                        _dynamicDataFolder = Project.ProjectItems.Item(DynamicDataFolderName);
                    }
                    catch (ArgumentException)
                    {
                        throw new Exception("The " + DynamicDataFolderName + " folder not found.");
                    }
                }
                return _dynamicDataFolder;
            }
        }

        private ProjectItem _filterTemplatesFolder;

        protected ProjectItem FilterTemplatesFolder
        {
            get
            {
                if (_filterTemplatesFolder == null)
                {
                    try
                    {
                        _filterTemplatesFolder = DynamicDataFolder.ProjectItems.Item(FilterTemplatesFolderName);
                    }
                    catch (ArgumentException)
                    {
                        return null;
                    }
                }
                return _filterTemplatesFolder;
            }
        }

        public bool FiltersExist
        {
            get
            {
                return FilterTemplatesFolder != null;
            }
        }

        public void CreateDefaultFilters()
        {
            CopyTemplateFiles(DynamicDataFolder, GetDefaultFilterTempaltesPath());
            ReplaceNamespace();
        }

        private void CopyTemplateFiles(ProjectItem folder, string templatePath)
        {
            folder.ProjectItems.AddFromDirectory(templatePath);
        }

        protected void ReplaceParameter(string parameterName, string value)
        {
            Find find = Project.DTE.Find;
            find.Action = vsFindAction.vsFindActionReplaceAll;
            find.Backwards = false;
            find.FindWhat = parameterName;
            find.FilesOfType = "*.*";
            find.KeepModifiedDocumentsOpen = false;
            find.MatchCase = true;
            find.MatchInHiddenText = true;
            find.MatchWholeWord = true;
            find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral;
            find.ReplaceWith = value;
            find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone;
            find.SearchPath = (string)FilterTemplatesFolder.Properties.Item("FullPath").Value;
            find.Target = vsFindTarget.vsFindTargetFiles;
            find.Execute();
        }

        protected string GetDefaultFilterTempaltesPath()
        {
#if DEBUG
            return string.Format(@"D:\Catalyst\Projects\DynamicData\Project\Trunk\DynamicData\Setup\Templates\{0}\{1}", LanguageTemplateFolder, FilterTemplatesFolderName);
#else
            string programFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
            return string.Format(@"{0}\Dynamic Data Filtering\Templates\{1}\{2}", programFilesPath, LanguageTemplateFolder, FilterTemplatesFolderName);
#endif 
        }

        protected abstract string LanguageTemplateFolder { get; }

        protected abstract void ReplaceNamespace();

    }
}
